package widgets

import (
	"encoding/json"
	"strings"
	"time"

	"gitee.com/nanakura/imgui-restclient/db/model"
	g "github.com/AllenDang/giu"
	"github.com/atotto/clipboard"
	"github.com/imroc/req/v3"
)

func (app *MyApp) RequestTabItem() *g.TabItemWidget {
	return g.TabItem("请求").Layout(
		g.Row(
			g.Combo("",
				app.requestTypes[app.requestType],
				app.requestTypes,
				&app.requestType,
			).Size(90),
			g.Spacing(),
			g.InputText(&app.url),
			g.Spacing(),
			g.Button("请求").OnClick(app.request),
		),
		g.Separator(),
		g.TabBar().TabItems(
			g.TabItem("请求参数").Layout(
				g.Row(
					g.Label("参数名："),
					g.InputText(&app.tmpParamsPairK).Size(200),
					g.Spacing(),
					g.Label("值："),
					g.InputText(&app.tmpParamsPairV).Size(200),
					g.Spacing(),
					g.Button("添加").OnClick(func() {
						if app.tmpParamsPairK != "" && app.tmpParamsPairV != "" {
							for _, pair := range app.paramsPairs {
								if app.tmpParamsPairK == pair.K {
									g.Msgbox("Warn", "该请求参数已存在")
									return
								}
							}

							app.paramsPairs = append(app.paramsPairs, Pair{K: app.tmpParamsPairK, V: app.tmpParamsPairV})
							app.tmpParamsPairK = ""
							app.tmpParamsPairV = ""
						}
					}),
					g.Button("删除").OnClick(func() {
						if len(app.paramsPairs) > 0 {
							app.paramsPairs = app.paramsPairs[:len(app.paramsPairs)-1]
						}
					}),
					g.Button("清除").OnClick(func() {
						if len(app.headersPairs) > 0 {
							app.paramsPairs = []Pair{}
						}
					}),
				),
				g.Table().
					Columns(
						g.TableColumn("请求参数"),
						g.TableColumn("值"),
						g.TableColumn("操作"),
					).
					Rows(
						app.ParamsRows()...,
					).Size(g.Auto, 163.3),
			),
			g.TabItem("请求头").Layout(
				g.Row(
					g.Label("请求头名："),
					g.InputText(&app.tmpHeaderPairK).Size(200),
					g.Spacing(),
					g.Label("值："),
					g.InputText(&app.tmpHeaderPairV).Size(200),
					g.Spacing(),
					g.Button("添加").OnClick(func() {
						if app.tmpHeaderPairK != "" && app.tmpHeaderPairV != "" {
							for _, pair := range app.headersPairs {
								if app.tmpHeaderPairK == pair.K {
									g.Msgbox("Warn", "该请求头已存在")
									return
								}
							}

							app.headersPairs = append(app.headersPairs, Pair{K: strings.TrimSpace(app.tmpHeaderPairK), V: strings.TrimSpace(app.tmpHeaderPairV)})
							app.tmpHeaderPairK = ""
							app.tmpHeaderPairV = ""
						}
					}),
					g.Button("删除").OnClick(func() {
						if len(app.headersPairs) > 0 {
							app.headersPairs = app.headersPairs[:len(app.headersPairs)-1]
						}
					}),
					g.Button("清除").OnClick(func() {
						if len(app.headersPairs) > 0 {
							app.headersPairs = []Pair{}
						}
					}),
				),
				g.Table().
					Columns(
						g.TableColumn("请求头"),
						g.TableColumn("值"),
						g.TableColumn("操作"),
					).
					Rows(
						app.HeadersRows()...,
					).Size(g.Auto, 163.3),
			),
			g.TabItem("请求体").Layout(
				g.Row(
					g.Label("Content-Type"),
					g.Combo("",
						app.contentTypes[app.contentType],
						app.contentTypes,
						&app.contentType,
					).Size(200),
					g.Button("清除").OnClick(func() {
						app.reqBodyEditor.Text("")
						app.contentType = 0
					}),
				),
				app.reqBodyEditor,
			),
		),
		g.Separator(),
		g.Row(
			g.Label("请求结果"),
			g.Spacing(),
			g.Button("复制").OnClick(func() {
				if app.reqResp != "" {
					clipboard.WriteAll(app.reqResp)
				}
			}),
		),
		g.Label(app.reqResp).Wrapped(true),
	)
}

func (app *MyApp) request() {
	r := app.httpClient.R()
	params := make(map[string]string)
	if len(app.paramsPairs) != 0 {
		for _, v := range app.paramsPairs {
			params[v.K] = v.V
		}
		r.SetQueryParams(params)
	}
	headers := make(map[string]string)
	headers["Content-Type"] = app.contentTypes[app.contentType]
	if len(app.headersPairs) != 0 {
		for _, v := range app.headersPairs {
			headers[v.K] = v.V
		}
	}
	r.SetHeaders(headers)

	if app.reqBodyEditor.GetText() != "" {
		r.SetBody(app.reqBodyEditor.GetText())
	}

	var resp *req.Response
	var err error
	startTime := time.Now()
	method := app.requestTypes[app.requestType]
	url := strings.TrimSpace(app.url)
	switch method {
	case "GET":
		resp, err = r.Get(url)
	case "POST":
		resp, err = r.Post(url)
	case "PUT":
		resp, err = r.Put(url)
	case "DELETE":
		resp, err = r.Delete(url)
	default:
		panic("unreachable")
	}
	elapsed := time.Since(startTime)
	headerJson, _ := json.Marshal(headers)
	paramsJson, _ := json.Marshal(params)
	if err != nil {
		app.reqResp = err.Error()
		return
	}
	app.reqResp = resp.String()
	if json.Valid([]byte(app.reqResp)) {
		var data interface{}
		json.Unmarshal([]byte(app.reqResp), &data)
		formattedJSON, _ := json.MarshalIndent(data, "", "  ")
		app.reqResp = string(formattedJSON)
	}
	history := model.History{
		Method:      method,
		Url:         url,
		Headers:     string(headerJson),
		Params:      string(paramsJson),
		Body:        app.reqBodyEditor.GetText(),
		ContentType: app.contentType,
		Response:    resp.Status,
		Date:        startTime,
		Time:        int32(elapsed.Milliseconds()),
	}
	model.InsertHistory(history)
	app.refreshHistory()
}
